#define _CRT_SECURE_NO_WARNINGS 1

#include"My_string.h"

namespace bit
{
	string::string(const char* str)
		: _size(strlen(str))
		, _capacity(_size)
	{
		_str = new char[_capacity+1];
		strcpy(_str, str);
	}

	//string::string(const string& str)
	//	:_size(str._size)
	//	,_capacity(str._capacity)
	//{
	//	_str = new char[_capacity+1];
	//	strcpy(_str, str._str);
	//}

	string::string(const string& str)
	{
		string tmp(str._str);
		std::swap(_str, tmp._str);
		std::swap(_size, tmp._size);
		std::swap(_capacity, tmp._capacity);
	}

	const char* string::c_str()const
	{
		return _str;
	}

	string& string::operator=(const string& str)
	{
		if (this != &str)
		{
			//_size = str._size;
			//_capacity = str._capacity;
			//delete[] _str;
			//_str = new char[_capacity+1];
			//strcpy(_str, str._str);
			//return *this;
			string tmp(str._str);
			swap(tmp);
		}
		return *this;
	}

	size_t string::size()const
	{
		return _size;
	}

	char& string::operator[](size_t pos)
	{
		assert(_size > pos);
		return _str[pos];
	}

	const char& string::operator[](size_t pos)const
	{
		assert(_size > pos);
		return _str[pos];
	}

	iterator string::begin()
	{
		return _str;
	}

	const_iterator string::begin()const
	{
		return _str;
	}

	iterator string:: end()
	{
		return _str + _size;
	}

	const_iterator string::end()const
	{
		return _str + _size;
	}

	size_t string::capacity()const
	{
		return _capacity;
	}

	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* c = new char[n+1];
			_capacity = n;
			strcpy(c, _str);
			delete[] _str;
			_str = c;
		}
	}

	string& string::push_back(char c)
	{
		//if (_size == _capacity)
		//{
		//	size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
		//	//char* ch = new char[newcapacity];
		//	//strcpy(ch, _str);
		//	//delete[] _str;
		//	//_str = ch;
		//	//_capacity = newcapacity;
		//	reserve(newcapacity);
		//}
		//_str[_size++] = c;
		//_str[_size] = '\0';
		insert(_size, c);
		return *this;
	}

	string& string::append(const string& str)
	{
		//size_t st = strlen(str._str);
		//if (_size + st > _capacity)
		//{
		//	reserve(_size + st);
		//}
		//strcpy(_str + _size, str._str);
		//_size = _size + st;
		insert(_size, str);
		return *this;
	}

	string& string::insert(size_t pos, const string& str, size_t st, size_t len)
	{
		assert(pos <= _size);
		if ((_size + str._size) > _capacity)
		{
			reserve(_size + str._size);
		}
		int s, i;
		if (len < (str._size - st))
		{
			s = _size;
			i = _size + len;
		}
		else
		{
			s = _size;
			i = _size + str._size - st;
			len = str._size - st;
		}
		while (1)
		{
			if (s >= (int)pos)
			{
				_str[i] = _str[s];
				i--;
				s--;
			}
			else if (len > 0)
			{
				_str[pos++] = str[st++];
				len--;
				_size++;
			}
			else
			{
				return *this;
			}
		}
		return *this;
	}

	string& string::insert(size_t pos, char c)
	{
		assert(pos <= _size);
		if (_size == _capacity)
		{
			reserve(_capacity + 1);
		}
		int i = _size;
		while (i >= (int)pos)
		{
			_str[i + 1] = _str[i];
			i--;
		}
		_str[pos] = c;
		_size++;
		return *this;
	}

	void string::erase(size_t pos, size_t len)
	{
		assert(pos <= _size);
		if (len >= _size - pos)
		{
			_str[pos] = '\0';
			_size = pos - 1;
		}
		else
		{
			//while (1)
			//{
			//	_str[pos] = _str[pos + len];
			//	if (_str[pos + len] == '\0')
			//	{
			//		break;
			//	}
			//	pos++;
			//}
			//_size = pos;
			strcpy(&_str[pos], &_str[pos + len]);
			_size = strlen(_str);
		}
	}

	size_t string::find(const string& st, size_t pos)const
	{
		assert(pos < _size);
		char* p = strstr(&_str[pos], st._str);
		if (p != nullptr)
		{
			return p - _str;
		}
		return npos;
	}

	size_t string::find(char c, size_t pos)const
	{
		assert(pos < _size);
		size_t i = pos;
		while (_str[i] != c && i < _size)
		{
			i++;
			if (i >= _size)
			{
				return npos;
			}
		}
		return i;
	}

	void string::swap(string& s1)
	{
		std::swap(_str,s1._str);
		std::swap(_size,s1._size);
		std::swap(_capacity,s1._capacity);
	}

	string string::substr(size_t pos, size_t len)const
	{
		assert(pos < _size);
		string s1;
		s1.insert(0,_str,pos,len);
		return s1;
	}

	string& string::operator+=(const string& s1)
	{
		append(s1);
		return *this;
	}

	string& string::operator+=(char c)
	{
		insert(_size, c);
		return *this;
	}

	bool string::operator>(const string& s)const
	{
		return strcmp(_str, s._str) > 0;
	}

	bool string::operator<(const string& s)const
	{
		return strcmp(_str, s._str) < 0;
	}

	bool string::operator<=(const string& s) const
	{
		return !(*this > s);
	}

	bool string::operator>=(const string& s) const
	{
		return !(*this < s);
	}

	bool string::operator==(const string& s) const
	{
		return strcmp(_str, s._str) == 0;
	}

	bool string::operator!=(const string& s) const
	{
		return !(*this == s);
	}

	void string::clear()
	{
		if (*this != "")
		{
			_str[0] = '\0';
			_size = 0;
		}
	}


	string:: ~string()
	{
		delete[] _str;
		_size = 0;
		_capacity = 0;
	}

	void swap(string& s1, string& s2)
	{
		s1.swap(s2);
	}

	istream& operator>> (istream& is, string& str)
	{
		char c;
		char ch[128];
		str.clear();
		int i = 0;
		while (i<128)
		{
			is.get(c);
			if (c == '\n'||c == ' ')
			{
				ch[i] = '\0';
				break;
			}
			ch[i] = c;
			i++;
			if (i == 127)
			{
				ch[i] = '\0';
				str += ch;
				i = 0;
			}
		}
		if (i != 0)
		{
			str += ch;
		}
		
		return is;
	}
	ostream& operator<< (ostream& os, const string& str)
	{
		os << str.c_str();
		return os;
	}

}